home *** CD-ROM | disk | FTP | other *** search
- /*
-
- flexlist.c
- 10-4-90
- Homogeneous-heterogeneous
- hybrid stack-queue-list-array generic class.
- ANSI C
-
- Copyright 1990
- John W. Small
- All rights reserved
-
- PSW / Power SoftWare
- P.O. Box 10072,
- McLean, Virginia 22102 8072
- (703) 759-3838
-
- */
-
-
- #include <flexlist.h> /* <stddef.h> size_t */
- #include <stdlib.h> /* malloc(), free() */
- #include <string.h> /* memcpy(), memset() */
-
-
- /* String variant FlexNode virtual functions */
-
- /*
- FNnew() is called by FlexList functions (primitives)
- that need to allocate new variant length FlexNodes,
- e.g. FLpushD(), FLinsQD(), FLinsD(), FLinsSortD().
- A pointer to the data to be placed in the new node
- is passed to FNnew(). Your FNnew() function must
- decide how large that data is and allocate a new
- FlexNode big enough to hold that data, i.e.
-
- FlexN N = malloc(sizeof(FlexNode) +
- sizeofYourData - 1).
-
- Your FNnew() function must also copy that data to
- the new node. "D" is never NULL!
-
- Please note that FNnew() could call a known function
- pointer (function) in the data to determine its size.
- It could also call another function to copy/
- initialize the FlexNode data area from the data.
- Data that contains its own functions for interfacing
- with itself are called objects. Thus FlexLists can
- be made to hold polymorphic objects via the
- virtual function table functionology.
-
- Study all four virtual functions FNnew(), FNwrite(),
- FNread(), and FNdestruct() for strings and how they
- are called by the various FlexList functions to get
- a better understanding of variant FlexLists.
- */
-
- static FlexN FNnewStr(const void *D)
- {
- FlexN N;
- size_t i;
-
- for (i = 0; ((char *)D)[i++]; /* no reinit */)
- /* null statement */;
- if ((N = malloc(sizeof(FlexNode)+i-1)) != FlexN0)
- (void) memcpy(N->data,D,i);
- return N;
- }
-
-
- /* FNwrite() is called by FLstoreD() to write variant data
- to a variant FlexNode. Make sure the new data
- doesn't write pass the end of the old. FNwrite()
- returns true if the write is successful. "ND" and
- "D" are never NULL! */
-
- static int FNwriteStr(void *ND, const void *D)
- {
- char *nd, *d;
-
- nd = (char *) ND;
- d = (char *) D;
- while (*nd)
- if ((*nd++ = *d++) == '\0')
- break;
- return 1;
- }
-
- /* FNread() is called by FLtopD(), FLnextD(),
- FLprevD(), and FLrecallD() to read variant data
- from a variant FlexNode. FNread() returns true if
- the read is successful. "ND" and "D" are never
- NULL! */
-
- static int FNreadStr(const void *ND, void *D)
- {
- char *nd, *d;
-
- nd = (char *) ND;
- d = (char *) D;
- while ((*d++ = *nd++) != '\0')
- /* null statement */;
- return 1;
- }
-
- /* FNdestruct() is called by FLclear(), FLdelete() via
- Flclear(), FLpopD(), and FLdelD() to destruct
- variant data in a FlexNode. Please note that
- references to suballocated memory may be copied
- to the outgoing data structure instead of being
- cloned and then deallocated. You must keep any
- scheme straight though. FLclear() always passes
- NULL to the second parameter of FNdestruct() via
- a call to FLpopD(L,0), however, so any
- suballocated memory must be freed in that case!
- "ND" is never NULL but "D" can be! */
-
- static int FNdestructStr(void *ND, void *D)
- {
- char *nd, *d;
-
- nd = (char *)ND;
- if ((d = (char *)D) != (char *)0)
- while ((*d++ = *nd++) != '\0')
- /* null statement */;
- return 1;
- }
-
- /* Any of the virtual functions can be absent. The FlexList
- functions that call them will simply return a failure
- indication. Use FNnew0, FNwrite0, FNread0, and/or
- FNdestruct0 as zero initializers. */
-
- FlexNodeVFT FlexNodeStrVFT = {
- FNnewStr, FNwriteStr, FNreadStr, FNdestructStr };
-
-
- /* FlexList constructors/destructor - static headers */
-
-
- #define FLzero(L) memset((void *)(L),0,sizeof(FlexList)-1)
-
- FlexL FLfixed(FlexL L, size_t sizeofNodeData)
- {
- if (!L)
- return L;
- (void) FLzero(L);
- if (!sizeofNodeData || sizeofNodeData
- > FLmaxSizeofNodeData)
- return FlexL0;
- L->maxNodes = FLmaxMaxNodes;
- L->sizeofNodeData = sizeofNodeData;
- L->sizeofNode = sizeof(FlexNode)
- + sizeofNodeData - 1;
- L->sorted = 1;
- return L;
- }
-
- FlexL FLunpack(FlexL L, size_t sizeofCell,
- unsigned cells, const void *array)
- {
- if (!L)
- return L;
- (void) FLzero(L);
- if ((sizeofCell > FLmaxSizeofNodeData) ||
- !sizeofCell || !cells || !array)
- return FlexL0;
- L->maxNodes = FLmaxMaxNodes;
- L->sizeofNodeData = sizeofCell;
- L->sizeofNode = sizeof(FlexNode)
- + sizeofCell - 1;
- for (;cells && FLinsQD(L,array); cells--)
- array = (char *) array + sizeofCell;
- return L;
- }
-
- FlexL FLvariant(FlexL L, FlexNVFT vft)
- {
- if (!L)
- return L;
- (void) FLzero(L);
- if (!vft)
- return FlexL0;
- L->maxNodes = FLmaxMaxNodes;
- L->sorted = 1;
- L->vft = vft;
- return L;
- }
-
- int FLclear(FlexL L)
- {
- while (FLpopD(L,(void *)0))
- /* null statement */;
- if (L) if (!L->nodes)
- return (L->sorted = 1);
- return 0;
- }
-
- /* FlexList constructors/destructor - dynamic headers */
-
- /* FlexList headers are flagged as dynamic if and only if
- FLDdestruct != NULL. FLDmalloced() is the default
- function pointer whenever one isn't specified. */
- #pragma argsused
- /* ARGSUSED */
- static int FLDmalloced(void *LD)
- { /* LD is intentionally unused! */
- return 1;
- }
-
- static FlexL FLnew(size_t sizeofLocalData,
- int (*FLDdestruct)(void *LD))
- {
- FlexL L;
-
- if (sizeofLocalData > FLmaxSizeofLocalData)
- return FlexL0;
- L = (FlexL) malloc(sizeof(FlexList) +
- sizeofLocalData - 1);
- if (L) {
- (void) FLzero(L);
- if (FLDdestruct)
- L->FLDdestruct = FLDdestruct;
- else
- L->FLDdestruct = FLDmalloced;
- }
- return L;
- }
-
- FlexL FLfixedNew(size_t sizeofNodeData,
- size_t sizeofLocalData,
- int (*FLDdestruct)(void *LD))
- {
- FlexL L;
-
- if (!sizeofNodeData || sizeofNodeData >
- FLmaxSizeofNodeData)
- return FlexL0;
- if ((L = FLnew(sizeofLocalData,FLDdestruct))
- != FlexL0) {
- L->maxNodes = FLmaxMaxNodes;
- L->sizeofNodeData = sizeofNodeData;
- L->sizeofNode = sizeof(FlexNode)
- + sizeofNodeData - 1;
- L->sorted = 1;
- }
- return L;
- }
-
- FlexL FLunpackNew(size_t sizeofCell,
- unsigned cells, const void *array,
- size_t sizeofLocalData,
- int (*FLDdestruct)(void *LD))
- {
- FlexL L;
-
- if ((sizeofCell > FLmaxSizeofNodeData) ||
- !sizeofCell || !cells || !array)
- return FlexL0;
- if ((L = FLnew(sizeofLocalData,FLDdestruct))
- != FlexL0) {
- L->maxNodes = FLmaxMaxNodes;
- L->sizeofNodeData = sizeofCell;
- L->sizeofNode = sizeof(FlexNode)
- + sizeofCell - 1;
- for (;cells && FLinsQD(L,array); cells--)
- array = (char *) array + sizeofCell;
- }
- return L;
- }
-
- FlexL FLvariantNew(FlexNVFT vft,
- size_t sizeofLocalData,
- int (*FLDdestruct)(void *LD))
- {
- FlexL L;
-
- if (!vft)
- return FlexL0;
- if ((L = FLnew(sizeofLocalData,FLDdestruct))
- != FlexL0) {
- L->maxNodes = FLmaxMaxNodes;
- L->sorted = 1;
- L->vft = vft;
- }
- return L;
- }
-
- int FLdelete(FlexL *Lptr)
- {
- if (!Lptr)
- return 0;
- if (!(*Lptr)->FLDdestruct)
- return 0;
- if (!(*((*Lptr)->FLDdestruct))((*Lptr)->data))
- return 0;
- if (!FLclear(*Lptr))
- return 0;
- free(*Lptr);
- *Lptr = FlexL0;
- return 1;
- }
-
-
- /* FlexList header functions */
-
- int FLsetMaxNodes(FlexL L, unsigned maxNodes)
- {
- if (L)
- if (maxNodes >= L->nodes) {
- L->maxNodes = maxNodes;
- return 1;
- }
- return 0;
- }
-
- int FLsetCompare(FlexL L, int (*compare)
- (const void *D1, const void *D2))
- {
- if (L) {
- L->compare = compare;
- L->sorted = 0;
- return 1;
- }
- return 0;
- }
-
-
- /* FlexList stack and queue functions */
-
- void * FLpushN(FlexL L, FlexN N)
- {
- if (!L || !N)
- return (void *) 0;
- if (L->nodes >= L->maxNodes)
- return (void *) 0;
- N->prev = FlexN0;
- if ((N->next = L->front) != FlexN0)
- N->next->prev = N;
- else
- L->rear = N;
- L->front = N;
- L->nodes++;
- if (L->curNum)
- L->curNum++;
- L->sorted = 0;
- return N->data;
- }
-
- void * FLpushD(FlexL L, const void *D)
- {
- FlexN N;
-
- if (!L)
- return (void *) 0;
- if (L->nodes >= L->maxNodes)
- return (void *) 0;
- if (L->sizeofNode) { /* fixed size FlexNodes */
- if ((N = malloc(L->sizeofNode)) == FlexN0)
- return (void *) 0;
- if (D)
- memcpy(N->data,D,L->sizeofNodeData);
- else
- memset(N->data,0,L->sizeofNodeData);
- }
- else if (!L->vft || !D)
- return (void *) 0;
- else if (!L->vft->FNnew)
- return (void *) 0;
- else if ((N = (*L->vft->FNnew)(D)) == FlexN0)
- return (void *) 0;
- N->prev = FlexN0;
- if ((N->next = L->front) != FlexN0)
- N->next->prev = N;
- else
- L->rear = N;
- L->front = N;
- L->nodes++;
- if (L->curNum)
- L->curNum++;
- L->sorted = 0;
- return N->data;
- }
-
- FlexN FLpopN(FlexL L)
- {
- FlexN N;
-
- if (!L)
- return FlexN0;
- if ((N = L->front) == FlexN0)
- return FlexN0;
- if (L->front == L->rear)
- L->rear = FlexN0;
- else
- N->next->prev = FlexN0;
- L->front = N->next;
- L->nodes--;
- if (L->curNum)
- if (!--L->curNum)
- L->current = FlexN0;
- N->next = N->prev = FlexN0;
- return N;
- }
-
- int FLpopD(FlexL L, void *D)
- {
- FlexN N;
-
- if (!L)
- return 0;
- if ((N = L->front) == FlexN0)
- return 0;
- if (L->sizeofNodeData) {
- if (D)
- memcpy(D,N->data,L->sizeofNodeData);
- }
- else if (!L->vft)
- return 0;
- else if (!L->vft->FNdestruct)
- return 0;
- else if (!(*L->vft->FNdestruct)(N->data,D))
- return 0;
- if (L->front == L->rear)
- L->rear = FlexN0;
- else
- N->next->prev = FlexN0;
- L->front = N->next;
- L->nodes--;
- if (L->curNum)
- if (!--L->curNum)
- L->current = FlexN0;
- free(N);
- return 1;
- }
-
- void * FLtopD(FlexL L, void *D)
- {
- if (!L)
- return (void *) 0;
- if (!L->front)
- return (void *) 0;
- if (D) if (L->sizeofNodeData)
- memcpy(D,L->front->data,L->sizeofNodeData);
- else if (!L->vft)
- return (void *) 0;
- else if (!L->vft->FNread)
- return (void *) 0;
- else if (!(*L->vft->FNread)(L->front->data,D))
- return (void *) 0;
- return L->front->data;
- }
-
- void * FLinsQN(FlexL L, FlexN N)
- {
- if (!L || !N)
- return (void *) 0;
- if (L->nodes >= L->maxNodes)
- return (void *) 0;
- N->next = FlexN0;
- if (L->rear)
- L->rear->next = N;
- else
- L->front = N;
- N->prev = L->rear;
- L->rear = N;
- L->nodes++;
- L->sorted = 0;
- return N->data;
- }
-
- void * FLinsQD(FlexL L, const void *D)
- {
- FlexN N;
-
- if (!L)
- return (void *) 0;
- if (L->nodes >= L->maxNodes)
- return (void *) 0;
- if (L->sizeofNode) { /* fixed size FlexNodes */
- if ((N = malloc(L->sizeofNode)) == FlexN0)
- return (void *) 0;
- if (D)
- memcpy(N->data,D,L->sizeofNodeData);
- else
- memset(N->data,0,L->sizeofNodeData);
- }
- else if (!L->vft || !D)
- return (void *) 0;
- else if (!L->vft->FNnew)
- return (void *) 0;
- else if ((N = (*L->vft->FNnew)(D)) == FlexN0)
- return (void *) 0;
- N->next = FlexN0;
- if (L->rear)
- L->rear->next = N;
- else
- L->front = N;
- N->prev = L->rear;
- L->rear = N;
- L->nodes++;
- L->sorted = 0;
- return N->data;
- }
-
- void * FLmkcur(FlexL L, unsigned n)
- {
- if (!L) return (void *) 0;
- if (!n || (n > L->nodes)) { /* out of range */
- L->current = 0;
- L->curNum = 0;
- return (void *) 0;
- }
- else if (n == L->curNum) /* already there */
- return L->current->data;
- if (L->current) /* divide list into two parts */
- if (n > L->curNum) /* in last half of list */
- if (((L->nodes >> 1) + (L->curNum >> 1)) < n)
- /* rear closest */
- for (L->current = L->rear, L->curNum = L->nodes;
- L->curNum > n; L->curNum--)
- L->current = L->current->prev;
- else /* current closest */
- for (;L->curNum < n; L->curNum++)
- L->current = L->current->next;
- else /* in first half of list */
- if ((L->curNum >> 1) < n) /* current closest */
- for (;L->curNum > n; L->curNum--)
- L->current = L->current->prev;
- else /* front closest */
- for (L->current = L->front, L->curNum = 1;
- L->curNum < n; L->curNum++)
- L->current = L->current->next;
- else /* consider whole list */
- if ((L->nodes >> 1) < n) /* closer to rear */
- for (L->current = L->rear, L->curNum = L->nodes;
- L->curNum > n; L->curNum--)
- L->current = L->current->prev;
- else /* closer to front */
- for (L->current = L->front, L->curNum = 1;
- L->curNum < n; L->curNum++)
- L->current = L->current->next;
- return L->current->data;
- }
-
- void * FLinsN(FlexL L, FlexN N)
- {
- if (!L || !N)
- return (void *) 0;
- if (L->nodes >= L->maxNodes)
- return (void *) 0;
- if ((N->prev = L->current) == FlexN0) {
- if ((N->next = L->front) == FlexN0)
- L->rear = N;
- else
- N->next->prev = N;
- L->front = N;
- }
- else { /* after current */
- if ((N->next = L->current->next) == FlexN0)
- L->rear = N; /* last node */
- else
- N->next->prev = N;
- L->current->next = N;
- }
- L->current = N;
- L->curNum++;
- L->nodes++;
- L->sorted = 0;
- return N->data;
- }
-
- void * FLinsD(FlexL L, const void *D)
- {
- FlexN N;
-
- if (!L)
- return (void *) 0;
- if (L->nodes >= L->maxNodes)
- return (void *) 0;
- if (L->sizeofNode) { /* fixed size FlexNodes */
- if ((N = malloc(L->sizeofNode)) == FlexN0)
- return (void *) 0;
- if (D)
- memcpy(N->data,D,L->sizeofNodeData);
- else
- memset(N->data,0,L->sizeofNodeData);
- }
- else if (!L->vft || !D)
- return (void *) 0;
- else if (!L->vft->FNnew)
- return (void *) 0;
- else if ((N = (*L->vft->FNnew)(D)) == FlexN0)
- return (void *) 0;
- if ((N->prev = L->current) == FlexN0) {
- if ((N->next = L->front) == FlexN0)
- L->rear = N;
- else
- N->next->prev = N;
- L->front = N;
- }
- else { /* after current */
- if ((N->next = L->current->next) == FlexN0)
- L->rear = N; /* last node */
- else
- N->next->prev = N;
- L->current->next = N;
- }
- L->current = N;
- L->curNum++;
- L->nodes++;
- L->sorted = 0;
- return N->data;
- }
-
- void * FLinsSortN(FlexL L, FlexN N)
- {
- unsigned long low, high;
- void *ok;
-
- if (!L || !N)
- return (void *) 0;
- if (L->nodes >= L->maxNodes || !L->compare)
- return (void *) 0;
- if (!L->sorted)
- (void) FLsort(L,FLcompare0);
- low = 1UL;
- high = (unsigned long) L->nodes;
- while (low <= high)
- if ((*L->compare)(FLmkcur(L,
- (unsigned)((low+high) >> 1)),
- N->data) <= 0)
- low = (unsigned long)
- (L->curNum + 1);
- else
- high = (unsigned long)
- (L->curNum - 1);
- (void) FLmkcur(L,(unsigned)high);
- ok = FLinsN(L,N);
- L->sorted = 1;
- return ok;
- }
-
- void * FLinsSortD(FlexL L, const void *D)
- {
- FlexN N;
- unsigned long low, high;
- void *ok;
-
- if (!L || !D)
- return (void *) 0;
- if (L->nodes >= L->maxNodes || !L->compare)
- return (void *) 0;
- if (L->sizeofNode) { /* fixed size FlexNodes */
- if ((N = malloc(L->sizeofNode)) == FlexN0)
- return (void *) 0;
- memcpy(N->data,D,L->sizeofNodeData);
- }
- else if (!L->vft)
- return (void *) 0;
- else if (!L->vft->FNnew)
- return (void *) 0;
- else if ((N = (*L->vft->FNnew)(D)) == FlexN0)
- return (void *) 0;
- if (!L->sorted)
- (void) FLsort(L,FLcompare0);
- low = 1UL;
- high = (unsigned long) L->nodes;
- while (low <= high)
- if ((*L->compare)(FLmkcur(L,
- (unsigned)((low+high) >> 1)),
- N->data) <= 0)
- low = (unsigned long)
- (L->curNum + 1);
- else
- high = (unsigned long)
- (L->curNum - 1);
- (void) FLmkcur(L,(unsigned)high);
- ok = FLinsN(L,N);
- L->sorted = 1;
- return ok;
- }
-
- FlexN FLdelN(FlexL L)
- {
- FlexN N;
-
- if (!L)
- return FlexN0;
- if ((N = L->current) == FlexN0)
- return FlexN0;
- L->current = N->prev;
- L->curNum--;
- if (N->next)
- N->next->prev = N->prev;
- else
- L->rear = N->prev;
- if (N->prev)
- N->prev->next = N->next;
- else
- L->front = N->next;
- L->nodes--;
- N->next = N->prev = FlexN0;
- return N;
- }
-
- int FLdelD(FlexL L, void *D)
- {
- FlexN N;
-
- if (!L)
- return 0;
- if ((N = L->current) == FlexN0)
- return 0;
- if (L->sizeofNodeData) {
- if (D)
- memcpy(D,N->data,L->sizeofNodeData);
- }
- else if (!L->vft)
- return 0;
- else if (!L->vft->FNdestruct)
- return 0;
- else if (!(*L->vft->FNdestruct)(N->data,D))
- return 0;
- L->current = N->prev;
- L->curNum--;
- if (N->next)
- N->next->prev = N->prev;
- else
- L->rear = N->prev;
- if (N->prev)
- N->prev->next = N->next;
- else
- L->front = N->next;
- L->nodes--;
- free(N);
- return 1;
- }
-
- void * FLnextD(FlexL L, void *D)
- {
- FlexN oldCurrent;
-
- if (!L)
- return (void *) 0;
- if ((oldCurrent = L->current) != FlexN0)
- L->current = L->current->next;
- else
- L->current = L->front;
- if (!L->current) {
- L->curNum = 0;
- return (void *) 0;
- }
- if (D) if (L->sizeofNodeData)
- memcpy(D,L->current->data,
- L->sizeofNodeData);
- else if (!L->vft) {
- L->current = oldCurrent;
- return (void *) 0;
- }
- else if (!L->vft->FNread) {
- L->current = oldCurrent;
- return (void *) 0;
- }
- else if (!(*L->vft->FNread)(L->current->data,D)) {
- L->current = oldCurrent;
- return (void *) 0;
- }
- L->curNum++;
- return L->current->data;
- }
-
- void * FLprevD(FlexL L, void *D)
- {
- FlexN oldCurrent;
- unsigned oldCurNum;
-
- if (!L)
- return (void *) 0;
- oldCurNum = L->curNum;
- if ((oldCurrent = L->current) != FlexN0) {
- L->current = L->current->prev;
- L->curNum--;
- }
- else {
- L->current = L->rear;
- L->curNum = L->nodes;
- }
- if (!L->current)
- return (void *) 0;
- if (D) if (L->sizeofNodeData)
- memcpy(D,L->current->data,
- L->sizeofNodeData);
- else if (!L->vft) {
- L->curNum = oldCurNum;
- L->current = oldCurrent;
- return (void *) 0;
- }
- else if (!L->vft->FNread) {
- L->curNum = oldCurNum;
- L->current = oldCurrent;
- return (void *) 0;
- }
- else if (!(*L->vft->FNread)(L->current->data,D)) {
- L->curNum = oldCurNum;
- L->current = oldCurrent;
- return (void *) 0;
- }
- return L->current->data;
- }
-
- void * FLfindFirstD(FlexL L, const void *D)
- {
- unsigned long low, high;
-
- if (!L || !D)
- return (void *) 0;
- if (!L->compare)
- return (void *) 0;
- if (L->sorted) {
- low = 1UL;
- high = (unsigned long) L->nodes;
- while (low <= high)
- if ((*L->compare)(FLmkcur(L,
- (unsigned)((low+high) >> 1)),D) < 0)
- low = (unsigned long) (L->curNum + 1);
- else
- high = (unsigned long) (L->curNum - 1);
- if (FLmkcur(L,(unsigned)high+1))
- if (!(*L->compare)(L->current->data,D))
- return L->current->data;
- /* leave at insertion point */
- (void) FLmkcur(L,(unsigned)high);
- }
- else {
- (void) FLmkcur(L,0);
- while (FLnextD(L,(void *)0))
- if (!(*L->compare)(L->current->data,D))
- return L->current->data;
- }
- return (void *) 0;
- }
-
- void * FLfindNextD(FlexL L, const void *D)
- {
- if (!L || !D)
- return (void *) 0;
- if (!L->compare)
- return (void *) 0;
- while (FLnextD(L,(void *)0))
- if (!(*L->compare)(L->current->data,D))
- return L->current->data;
- else if (L->sorted)
- break;
- return (void *) 0;
- }
-
- void * FLfindLastD(FlexL L, const void *D)
- {
- unsigned long low, high;
-
- if (!L || !D)
- return (void *) 0;
- if (!L->compare)
- return (void *) 0;
- if (L->sorted) {
- low = 1UL;
- high = (unsigned long) L->nodes;
- while (low <= high)
- if ((*L->compare)(FLmkcur(L,
- (unsigned)((low+high) >> 1)),D) <= 0)
- low = (unsigned long) (L->curNum + 1);
- else
- high = (unsigned long) (L->curNum - 1);
- if (FLmkcur(L,(unsigned)high))
- if (!(*L->compare)(L->current->data,D))
- return L->current->data;
- }
- else {
- (void) FLmkcur(L,0);
- while (FLprevD(L,(void *)0))
- if (!(*L->compare)(L->current->data,D))
- return L->current->data;
- }
- return (void *) 0;
- }
-
- void * FLfindPrevD(FlexL L, const void *D)
- {
- if (!L || !D)
- return (void *) 0;
- if (!L->compare)
- return (void *) 0;
- while (FLprevD(L,(void *)0))
- if (!(*L->compare)(L->current->data,D))
- return L->current->data;
- else if (L->sorted)
- break;
- return (void *) 0;
- }
-
- int FLsort(FlexL L, int (*compare)
- (const void *D1, const void *D2))
- {
- FlexList tmp;
-
- if (!L)
- return 0;
- if (L->sorted) {
- if (L->compare == compare || !compare)
- { FLmkcur(L,0); return 1; }
- }
- else if (!L->compare && !compare)
- return 0;
- if (compare)
- L->compare = compare;
- if (!L->nodes)
- return (L->sorted = 1);
- (void) FLzero(&tmp);
- tmp.maxNodes = FLmaxMaxNodes;
- tmp.sorted = 1;
- tmp.compare = L->compare;
- while (L->nodes)
- (void) FLinsSortN(&tmp,FLpopN(L));
- L->front = tmp.front;
- L->rear = tmp.rear;
- L->nodes = tmp.nodes;
- return (L->sorted = 1);
- }
-
- int FLstoreD(FlexL L, const void *D, unsigned n)
- {
- unsigned oldn;
-
- if (!L || !D)
- return 0;
- if (n > L->nodes || !n && !L->current)
- return 0;
- if (L->sizeofNodeData) {
- if (n) (void) FLmkcur(L,n);
- memcpy(L->current->data,D,
- L->sizeofNodeData);
- }
- else if (!L->vft)
- return 0;
- else if (!L->vft->FNwrite)
- return 0;
- else {
- oldn = L->curNum;
- if (n) (void) FLmkcur(L,n);
- if (!(*L->vft->FNwrite)(L->current->data,D))
- {
- (void) FLmkcur(L,oldn);
- return 0;
- }
- }
- L->sorted = 0;
- return 1;
- }
-
- int FLrecallD(FlexL L, void *D, unsigned n)
- {
- unsigned oldn;
-
- if (!L || !D)
- return 0;
- if (n > L->nodes || !n && !L->current)
- return 0;
- if (L->sizeofNodeData) {
- if (n) (void) FLmkcur(L,n);
- memcpy(D,L->current->data,
- L->sizeofNodeData);
- }
- else if (!L->vft)
- return 0;
- else if (!L->vft->FNread)
- return 0;
- else {
- oldn = L->curNum;
- if (n) (void) FLmkcur(L,n);
- if (!(*L->vft->FNread)(L->current->data,D))
- {
- (void) FLmkcur(L,oldn);
- return 0;
- }
- }
- return 1;
- }
-
- void * FLpack(FlexL L) /* Only fixed nodes! */
- {
- long sizeofArray;
- char *A, *Ai;
- FlexN N;
-
- if (!L) return (void *) 0;
- sizeofArray = ((long)L->sizeofNodeData)
- * ((long)L->nodes);
- if ((sizeofArray <= 0) ||
- (sizeofArray > FLmaxSizeofArray))
- return (void *) 0;
- if ((A = malloc((unsigned) sizeofArray))
- == (char *) 0)
- return (void *) 0;
- for (Ai = A, N = L->front; N; N = N->next,
- Ai += L->sizeofNodeData)
- memcpy(Ai,N->data,L->sizeofNodeData);
- return A;
- }
-
- void **FLpackPtrs(FlexL L)
- {
- long sizeofArray;
- void **A;
- unsigned Ai;
- FlexN N;
-
- if (!L) return (void **) 0;
- sizeofArray = sizeof(void *) * ((long)L->nodes + 1);
- if ((sizeofArray <= 0) ||
- (sizeofArray > FLmaxSizeofArray))
- return (void **) 0;
- if ((A = malloc((unsigned) sizeofArray))
- == (void **) 0)
- return (void **) 0;
- for (Ai = 0, N = L->front; N; Ai++, N = N->next)
- A[Ai] = N->data;
- A[Ai] = (void *) 0;
- return A;
- }
-